import os
import json
import re
import subprocess
from typing import Optional, Tuple, List, Dict, Any
import tempfile
import requests
from bs4 import BeautifulSoup

from .base_downloader import BaseDownloader, VideoInfo

class DouyinDownloader(BaseDownloader):
    """抖音视频下载器"""
    
    async def extract_video_info(self, url: str) -> Optional[VideoInfo]:
        """从抖音URL中提取视频信息"""
        try:
            # 使用yt-dlp获取视频信息
            cmd = [
                'yt-dlp', 
                '--dump-json',
                url
            ]
            
            result = subprocess.run(cmd, capture_output=True, text=True)
            
            if result.returncode != 0:
                print(f"yt-dlp错误: {result.stderr}")
                return None
            
            video_data = json.loads(result.stdout)
            
            # 提取标题和封面URL
            title = video_data.get('title', '未知标题')
            thumbnail_url = video_data.get('thumbnail', '')
            
            # 提取可用的格式
            formats = []
            for fmt in video_data.get('formats', []):
                if fmt.get('vcodec') != 'none':
                    format_info = {
                        'format_id': fmt.get('format_id'),
                        'format_note': fmt.get('format_note', ''),
                        'ext': fmt.get('ext', 'mp4'),
                        'width': fmt.get('width', 0),
                        'height': fmt.get('height', 0),
                        'fps': fmt.get('fps', 0),
                        'filesize': fmt.get('filesize', 0),
                        'format': fmt.get('format', '')
                    }
                    formats.append(format_info)
            
            # 按清晰度排序
            formats.sort(key=lambda x: (x.get('height', 0) or 0), reverse=True)
            
            return VideoInfo(title, thumbnail_url, formats)
        
        except Exception as e:
            print(f"提取抖音视频信息时出错: {str(e)}")
            return None
    
    async def download_video(self, url: str, format_id: str, progress_callback=None) -> Tuple[bool, str]:
        """下载抖音视频"""
        try:
            # 首先获取视频信息
            video_info = await self.extract_video_info(url)
            if not video_info:
                return False, "无法获取视频信息"
            
            # 创建安全的文件名
            safe_title = self.sanitize_filename(video_info.title)
            output_path = os.path.join(self.download_dir, f"{safe_title}.%(ext)s")
            
            # 构建下载命令
            cmd = [
                'yt-dlp',
                '-f', format_id,
                '-o', output_path,
                url
            ]
            
            # 执行下载
            process = subprocess.Popen(
                cmd, 
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=True
            )
            
            # 处理输出以更新进度
            for line in process.stdout:
                if progress_callback and '[download]' in line and '%' in line:
                    try:
                        # 尝试从输出中提取进度百分比
                        percent_str = line.split('%')[0].split()[-1]
                        percent = float(percent_str) / 100.0
                        progress_callback(percent)
                    except (ValueError, IndexError):
                        pass
            
            # 等待进程完成
            process.wait()
            
            if process.returncode != 0:
                error_message = process.stderr.read() if process.stderr else "未知错误"
                return False, f"下载失败: {error_message}"
            
            # 找到实际下载的文件
            for file in os.listdir(self.download_dir):
                if file.startswith(safe_title):
                    return True, os.path.join(self.download_dir, file)
            
            return False, "下载完成但找不到文件"
            
        except Exception as e:
            return False, f"下载过程中出错: {str(e)}" 